#include "../headers/main.h"
#include "../headers/glossaire.h"
#include "../headers/forces_symboliques.h"
#include "../headers/generation.h"


void getForceSymbolique(char* main,char* forceS) {
    int nb_cartes_main;
    for (nb_cartes_main = 0;main[nb_cartes_main] != '\0';nb_cartes_main++);
    
    trierCartes(main,ORDRE_CROISSANT);
    
    unsigned char i;
    for (i=0;i<=7;i++) { *(forceS + i) = '\0'; }
    
    //Test des différentes forces
    getQuinteFlush(main,forceS,nb_cartes_main);
    if (forceS[0] != '\0') return;
    getCarre(main,forceS,nb_cartes_main);
    if (forceS[0] != '\0') return;
    getFull(main,forceS,nb_cartes_main);
    if (forceS[0] != '\0') return;
    getFlush(main,forceS,nb_cartes_main);
    if (forceS[0] != '\0') return;
    getQuinte(main,forceS,nb_cartes_main);
    if (forceS[0] != '\0') return;
    getBrelan(main,forceS,nb_cartes_main);
    if (forceS[0] != '\0') return;
    getDoublePaire(main,forceS,nb_cartes_main);
    if (forceS[0] != '\0') return;
    getPaire(main,forceS,nb_cartes_main);
    if (forceS[0] != '\0') return;
    getHauteur(main,forceS,nb_cartes_main);
    
}

char* getMeilleureMain(char** mains, char* meilleure_main) {
    char* meilleure_force = malloc(7*sizeof(char));
    char* tmp_force = malloc(7*sizeof(char));
    unsigned long long puissance1, puissance2;
    unsigned long nb_mains;
    
    for (nb_mains=0;mains[nb_mains] != NULL; nb_mains++) {
        if (nb_mains == 0) {
            getForceSymbolique(mains[0],meilleure_force);
            strcpy(meilleure_main,mains[0]);
        }
        else {

            getForceSymbolique(mains[nb_mains],tmp_force);

            if (strcmp(tmp_force,"") != 0) {
                puissance1 = getPuissanceForce(tmp_force);
                puissance2 = getPuissanceForce(meilleure_force);
                if (puissance1 > puissance2) {
                    strcpy(meilleure_force,tmp_force);
                    strcpy(meilleure_main,mains[nb_mains]);
                }
                
            }
        }
    }
    
    free(tmp_force);
    free(meilleure_force);
    
    return meilleure_main;
}

void getQuinteFlush(char* main,char* force,int nb_cartes_main) {
    force[0] = '\0';

    int i,j,k = 0;
    int nb_couleur[4] = {0,0,0,0};
    for (i=0;i<nb_cartes_main;i++) { nb_couleur[getCouleur(main[i])]++; }
    
    for (i=0;i<4;i++) {
        if (nb_couleur[i] >= 5) {
            //On a une couleur
            char* jeu_monochrome = malloc(8*sizeof(char));
            char* quinte = malloc(7*sizeof(char));
            for (j=0;j<nb_cartes_main;j++) {
                if (getCouleur(main[j]) == i) {
                    jeu_monochrome[k++] = main[j];
                }
            }
            jeu_monochrome[k] = '\0';
            getQuinte(jeu_monochrome,quinte,k);
            if (quinte[0] == QUINTE) {
                force[0] = QUINTEFLUSH;
                force[1] = quinte[1];
                force[2] = '\0';
            }
            free(jeu_monochrome);
            free(quinte);
            break;
        }
    }
    
    
    
}

void getCarre(char* main,char* force,int nb_cartes_main) {
    force[0] = '\0';
    int i, j, k, l;
    char current_val;
    for (i=(nb_cartes_main-1);i>=0;i--) {
        current_val = getValeur(main[i]);
        for (j=i-1;j>=0;j--) {
            if ( current_val == getValeur(main[j]) ) {
                //Une autre valeur identique est trouvée dans la main
                for (k=j-1;k>=0;k--) {
                    if ( current_val == getValeur(main[k]) ) {
                        
                        for (l=k-1;l>=0;l--) {
                            if ( current_val == getValeur(main[l]) ) {
                          
                                force[0] = CARRE;
                                force[1] = current_val;
                                force[3] = '\0';
                                for (l=(nb_cartes_main-1);l>=0;l--) {
                                    if (current_val != getValeur(main[l])) {
                                        force[2] = getValeur(main[l]);
                                        return;
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}

void getFull(char* main,char* force,int nb_cartes_main) {
    force[0] = '\0';
    char* tmp_force = malloc(7*sizeof(char));
    getBrelan(main,tmp_force,7);
    if (tmp_force[0] == BRELAN) {
        force[1] = getValeur(tmp_force[1]);
        int i,j=0;
        char* mainSansBrelan = malloc((nb_cartes_main-2)*sizeof(char));
        mainSansBrelan[(nb_cartes_main-1)] = '\0';
        for (i=0;i<nb_cartes_main;i++) {
            if (tmp_force[1] != getValeur(main[i])) {
                mainSansBrelan[j++] = getValeur(main[i]);
            }
        }
        getPaire(mainSansBrelan,tmp_force,(nb_cartes_main-3));
        if (tmp_force[0] == PAIRE) {
            force[0] = FULL;
            force[2] = getValeur(tmp_force[1]);
            force[3] = '\0';
        }
        
        free(mainSansBrelan);
    }
    
    free(tmp_force);
}

void getFlush(char* main,char* force,int nb_cartes_main) {
    force[0] = '\0';

    int i,j,k = 1;
    int nb_couleur[4] = {0,0,0,0};
    for (i=0;i<nb_cartes_main;i++) {
        nb_couleur[getCouleur(main[i])]++;
    }
    for (i=0;i<4;i++) {
        if (nb_couleur[i] >= 5) {
            force[0] = COULEUR;
            for (j=(nb_cartes_main-1);j>=0;j--) {
                if (getCouleur(main[j]) == i) {
                    force[k++] = getValeur(main[j]);
                }
                if (k==6) { break; }
            }
            force[6] = '\0';
        }
    }
}

void getQuinte(char* main,char* force,int nb_cartes_main) {
    force[0] = '\0';
    char* main_test = getValeurs(main,nb_cartes_main);
    
    if (!mainContientCarte(main_test,DEUX)
        || !mainContientCarte(main_test,TROIS)
        || !mainContientCarte(main_test,QUATRE)
        || !mainContientCarte(main_test,CINQ)
        || !mainContientCarte(main_test,AS)
       ) {
        int i,val,nb_cartes_consecutives = 1;
        char best = main_test[nb_cartes_main-1];
        int val_suivante = -1;
        
        for (i=(nb_cartes_main-1);i>0;i--) {
            
            val = (val_suivante > -1) ? val_suivante : main_test[i];
            val_suivante = main_test[i-1];
            
            if (val == val_suivante) { continue; }
            
            if ((val-val_suivante) == 4) {
                nb_cartes_consecutives++;
            }
            else {
                best = val;
                nb_cartes_consecutives = 1;
            }
            if (nb_cartes_consecutives == 5) {
                force[0] = QUINTE;
                force[1] = best;
                force[2] = '\0';
            }
        }
        
    }
    else {
        //On a pas return, c'est une quinte spéciale
        force[0] = QUINTE;
        force[1] = CINQ;
        if (mainContientCarte(main_test,SIX)) {
            force[1] = SIX;
            if (mainContientCarte(main_test,SEPT)) {
                force[1] = SEPT;
            }
        }
        force[2] = '\0';
    }
    
    free(main_test);
}

void getBrelan(char* main,char* force,int nb_cartes_main) {
    force[0] = '\0';
    int i, j, k, l, num_carte, current_val;
    for (i=(nb_cartes_main-1);i>=0;i--) {
        current_val = getValeur(main[i]);
        for (j=i-1;j>=0;j--) {
            if ( current_val == getValeur(main[j]) ) {
                //Une autre valeur identique est trouvée dans la main
                for (k=j-1;k>=0;k--) {
                    if ( current_val == getValeur(main[k]) ) {
                        force[0] = BRELAN;
                        force[1] = current_val;
                        num_carte = 2;
                        for (l=(nb_cartes_main-1);l>=0;l--) {
                            if ((l != i) && (l != j) && (l != k)) {
                                force[num_carte++] = getValeur(main[l]);
                            }
                            if (num_carte == 5) { break; }
                        }
                        force[5] = '\0';
                        return;
                    }
                    
                }
                
            }
        }
    }
    
}

void getDoublePaire(char* main,char* force,int nb_cartes_main) {
   force[0] = '\0';
   char* paire = malloc(7*sizeof(char));
   getPaire(main,paire,nb_cartes_main);
   
   if (paire[0] == PAIRE) {
       force[2] = paire[1];
       //Une paire a été trouvée, on en cherche une autre
       int i,j=0;
       char* mainMoinsPaire = malloc((nb_cartes_main-1)*sizeof(char));
       for (i=0;i<nb_cartes_main;i++) {
           if (getValeur(main[i]) != paire[1]) {
               mainMoinsPaire[j++] = getValeur(main[i]);
           }
       }
       mainMoinsPaire[j] = '\0';
       getPaire(mainMoinsPaire,paire,nb_cartes_main-2);
       if (paire[0] == PAIRE) {
           force[0] = DOUBLE_PAIRE;
           force[1] = paire[1];
           for (i=0;mainMoinsPaire[i] != '\0';i++) {
               if (getValeur(mainMoinsPaire[i]) != paire[1]) {
                   force[3] = getValeur(mainMoinsPaire[i]);
               }
           }
       }
       free(mainMoinsPaire);
   }
   free(paire);
}

void getPaire(char* main,char* force,int nb_cartes_main) {
    force[0] = '\0';
    int i, j, k,current_val,num_carte=0;
    
    for (i=nb_cartes_main;i>=0;i--) {
        current_val = getValeur(main[i]);
        for (j=i-1;j>=0;j--) {
            if ( current_val == getValeur(main[j]) ) {
                //Une autre valeur identique est trouvée dans la main
                force[num_carte++] = PAIRE;
                force[num_carte++] = current_val;
                //Récupération des cartes restantes
                for (k=(nb_cartes_main-1);k>=0;k--) {
                    if (getValeur(main[k]) != current_val) { force[num_carte++] = getValeur(main[k]); }
                    if ((nb_cartes_main == 3) && (num_carte == 3)) { force[4] = '\0';break; }
                    if (num_carte == 5) { break; }
                }
                force[5] = '\0';
                return;
            }
        }
    }
}

void getHauteur(char* main,char* force,int nb_cartes_main) {

    unsigned char i = nb_cartes_main;
    
    //Trier les cartes par ordre décroissant
    force[0] = HAUTEUR;
    while (i > 0) {
        force[(nb_cartes_main+1)-i] = getValeur(main[i-1]);
        i--;
    }
    force[(nb_cartes_main+1)] = '\0';
}

void trierForces(Forces** forces,unsigned int nb_forces) {
    int permutation = 1;
    unsigned int i;
    Forces* tmp_force;
    
    //Tri à bulles : dès qu'on rencontre une figure plus grande, on permute
    while (permutation > 0) {
        permutation = 0;
        
        for (i = 0;i < (nb_forces-1);i++) {
            
            if (forces[i]->force_symbolique[0] < forces[i+1]->force_symbolique[0]) {
                tmp_force = forces[i];
                forces[i] = forces[i+1];
                forces[i+1] = tmp_force;     
                permutation = 1;
            }            
        }
        
    }
    
    unsigned long long puissance1;
    unsigned long long puissance2;
    permutation = 1;
    //Second tri 
    while (permutation > 0) {
        permutation = 0;
        
        for (i = 0;i < (nb_forces-1);i++) {
            
            if (forces[i]->force_symbolique[0] == forces[i+1]->force_symbolique[0]) {
                puissance1 = getPuissanceForce(forces[i]->force_symbolique);
                puissance2 = getPuissanceForce(forces[i+1]->force_symbolique);
                if (puissance1 < puissance2) {
                    tmp_force = forces[i];
                    forces[i] = forces[i+1];
                    forces[i+1] = tmp_force;     
                    permutation = 1;
                }

            }            
        }
        
    }  
    
}

unsigned long long getPuissanceForce(char* force) {
    int i,j,k=4;
    unsigned long long facteur;
    unsigned long long puissance;
    puissance = force[0]*100000000000;
    
    for (i=1;force[i]!='\0';i++) {
        facteur = 1;
        
        for (j=0;j<k;j++) {
            facteur *= 100;
        }
        puissance += force[i]*facteur;
        k--;
    }
    return puissance;
}
